package com.ruyuan.user.server.controller;

import com.ruyuan.common.model.PageDTO;
import com.ruyuan.common.web.model.WebResponse;
import com.ruyuan.gateway.sdk.facade.RuyuanGatewayFacade;
import com.ruyuan.gateway.sdk.model.AccountInfoToken;
import com.ruyuan.gateway.sdk.model.UserAccountInfo;
import com.ruyuan.gateway.sdk.model.UserAuthorities;
import com.ruyuan.user.api.model.constants.UserAccountInfoExtendKeys;
import com.ruyuan.user.server.controller.converter.WebJobConverter;
import com.ruyuan.user.server.controller.converter.WebUserConverter;
import com.ruyuan.user.server.controller.request.*;
import com.ruyuan.user.server.controller.response.CurrentUserVO;
import com.ruyuan.user.server.controller.response.UserListInfoVO;
import com.ruyuan.user.server.controller.response.UserMultiJobVO;
import com.ruyuan.user.server.domain.model.Authority;
import com.ruyuan.user.server.domain.model.Job;
import com.ruyuan.user.server.domain.model.User;
import com.ruyuan.user.server.domain.service.JobDomainService;
import com.ruyuan.user.server.domain.service.RoleDomainService;
import com.ruyuan.user.server.domain.service.UserDomainService;
import com.ruyuan.user.server.domain.service.request.PageQueryUserParam;
import com.ruyuan.user.server.domain.service.request.QueryUserAuthoritiesParam;
import com.ruyuan.user.server.domain.service.request.SaveUserMultiJobReq;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.*;
import java.util.stream.Collectors;

import static com.ruyuan.user.api.model.enums.AuthResourceTypeEnum.API;

/**
 * @author xx
 */
@Controller
@RequestMapping("/api/user")
public class UserController {

    @Autowired
    private UserDomainService userDomainService;

    @Autowired
    private WebUserConverter webUserConverter;

    @Autowired
    private RuyuanGatewayFacade ruyuanGatewayFacade;

    @Autowired
    private JobDomainService jobDomainService;

    @Autowired
    private WebJobConverter webJobConverter;

    @Autowired
    private RoleDomainService roleDomainService;

    @RequestMapping("/hello")
    @ResponseBody
    public String hello() {
        if (ruyuanGatewayFacade.getCurrentUser() == null) {
            return "not login";
        }
        return "i am " + ruyuanGatewayFacade.getCurrentUser().getUserName();
    }

    @RequestMapping("/doLogin")
    @ResponseBody
    public WebResponse<Boolean> doLogin(@Validated @RequestBody DoLoginRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return WebResponse.failWithMsg(bindingResult.getFieldError().getDefaultMessage());
        }
        User user = userDomainService.queryUserByUserName(request.getUserName());
        if (user == null) {
            return WebResponse.failWithMsg("用户名/密码错误");
        }
        boolean res = ruyuanGatewayFacade.login(new AccountInfoToken(request.getUserName(), request.getPassword(),
                username -> {
                    UserAccountInfo userAccountInfo = new UserAccountInfo();
                    userAccountInfo.setUserId(user.getId());
                    userAccountInfo.setUserName(user.getUserName());
                    userAccountInfo.setPassword(user.getPassword());
                    userAccountInfo.getExtendInfo().put(UserAccountInfoExtendKeys.ROOT_ORG_ID, String.valueOf(user.getRootOrgId()));
                    return userAccountInfo;
                }));
        if (!res) {
            return WebResponse.failWithMsg("用户名/密码错误");
        }
        reportUserAuthority(ruyuanGatewayFacade.getCurrentUser().getUserId());
        return WebResponse.successWithData(true);
    }

    private void reportUserAuthority(Long userId) {
        QueryUserAuthoritiesParam queryUserApiAuthoritiesParam = new QueryUserAuthoritiesParam();
        queryUserApiAuthoritiesParam.setUserId(userId);
        queryUserApiAuthoritiesParam.setTypeEnumList(Arrays.asList(API));
        List<Authority> apiAuthorities = roleDomainService.queryUserAllAuthorities(queryUserApiAuthoritiesParam);
        UserAuthorities userAuthorities = new UserAuthorities();
        userAuthorities.setUserId(userId);
        userAuthorities.setAuthorityCodes(Optional.ofNullable(apiAuthorities).orElse(new ArrayList<>()).stream()
                .map(Authority::getCode).collect(Collectors.toSet()));
        ruyuanGatewayFacade.reportUserAuthorities(userAuthorities);
    }

    @RequestMapping("/doLogout")
    @ResponseBody
    public WebResponse<Boolean> doLogout() {
        return WebResponse.successWithData(ruyuanGatewayFacade.logout());
    }

    @RequestMapping("/saveUser")
    @ResponseBody
    public WebResponse<Boolean> saveUser(@Validated @RequestBody SaveUserRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return WebResponse.failWithMsg(bindingResult.getFieldError().getDefaultMessage());
        }
        User user = webUserConverter.convertToUser(request);
        try {
            userDomainService.saveUser(user);
        } catch (Exception e) {
            return WebResponse.failWithMsg(e.getMessage());
        }
        return WebResponse.successWithData(true);
    }

    @RequestMapping("/currentUser")
    @ResponseBody
    public WebResponse<CurrentUserVO> currentUser() {
        Long userId = ruyuanGatewayFacade.getCurrentUser().getUserId();
        User user = userDomainService.queryUserById(userId);
        if (user != null) {
            return WebResponse.successWithData(webUserConverter.convertToCurrentUserVO(user));
        }
        return WebResponse.successWithData(null);
    }

    @RequestMapping("/queryUserList")
    @ResponseBody
    public WebResponse<PageDTO<UserListInfoVO>> queryUserList(QueryUserListWebRequest request) {
        PageQueryUserParam param = new PageQueryUserParam();
        BeanUtils.copyProperties(request, param);
        PageDTO<User> res = userDomainService.queryUserByPage(param);
        PageDTO<UserListInfoVO> pageDTO = PageDTO.of(res, Optional.ofNullable(res.getData()).map(
                webUserConverter::convertToUserListInfoVO).orElse(new ArrayList<>()));
        return WebResponse.successWithData(pageDTO);
    }

    @RequestMapping("/queryUserDetailInfo")
    @ResponseBody
    public WebResponse<CurrentUserVO> queryUserDetailInfo(Long userId) {
        User user = userDomainService.queryUserById(userId);
        if (user != null) {
            return WebResponse.successWithData(webUserConverter.convertToCurrentUserVO(user));
        }
        return WebResponse.successWithData(null);
    }

    @RequestMapping("/updatePsd")
    @ResponseBody
    public WebResponse<Boolean> updatePsd(@Validated @RequestBody UpdatePsdRequest updatePsdRequest, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return WebResponse.failWithMsg(bindingResult.getFieldError().getDefaultMessage());
        }
        Long userId = ruyuanGatewayFacade.getCurrentUser().getUserId();
        boolean res = userDomainService.updatePsd(userId, updatePsdRequest.getNewPsd());
        return WebResponse.successWithData(res);
    }

    @RequestMapping("/resetPsd")
    @ResponseBody
    public WebResponse<Boolean> resetPsd(@Validated @RequestBody ResetPsdRequest resetPsdRequest, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return WebResponse.failWithMsg(bindingResult.getFieldError().getDefaultMessage());
        }
        boolean res = userDomainService.updatePsd(resetPsdRequest.getUserId(), "1234");
        return WebResponse.successWithData(res);
    }

    @RequestMapping("/changeUserStatus")
    @ResponseBody
    public WebResponse<Boolean> changeUserStatus(@Validated @RequestBody ChangeUserStatusRequest changeUserStatusRequest, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return WebResponse.failWithMsg(bindingResult.getFieldError().getDefaultMessage());
        }
        User user = userDomainService.queryUserById(changeUserStatusRequest.getUserId());
        if (user == null) {
            return WebResponse.failWithMsg("用户不存在");
        }
        user.setIsDeleted(changeUserStatusRequest.isEnable() ? "n" : "y");
        userDomainService.saveUser(user);
        return WebResponse.successWithData(true);
    }

    @RequestMapping("/saveUserMultiJob")
    @ResponseBody
    public WebResponse<Boolean> saveUserMultiJob(@Validated @RequestBody SaveUserMultiJobRequest request, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return WebResponse.failWithMsg(bindingResult.getFieldError().getDefaultMessage());
        }
        SaveUserMultiJobReq req = webUserConverter.convertToSaveUserMultiJobReq(request);
        Boolean res = jobDomainService.saveUserMultiJob(req);
        return WebResponse.successWithData(res);
    }

    @RequestMapping("/queryUserMultiJob")
    @ResponseBody
    public WebResponse<UserMultiJobVO> queryUserMultiJob(Long userId) {
        User user = userDomainService.queryUserById(userId);
        UserMultiJobVO userMultiJobVO = new UserMultiJobVO();
        if (user.getMainJob() != null) {
            userMultiJobVO.setMainJob(webJobConverter.convertToJobListVO(Arrays.asList(user.getMainJob())).get(0));
        }
        if (MapUtils.isNotEmpty(user.getOtherJobs())) {
            userMultiJobVO.setMultiJobs(webJobConverter.convertToMultiJobListVO(user.getOtherJobs()));
        }
        return WebResponse.successWithData(userMultiJobVO);
    }

}
